%{
#define PROGRAM 	110
#define PROCEDURE 	111
#define FUNCTION 	112
#define CONST 		113
#define TYPE 		114
#define VAR 		115
#define ARRAY 		116
#define BOOLEAN 	117	
#define CHAR 		118
#define INTEGER 	119
#define REAL 		120
#define RECORD 		121
#define BEGIN_ 		122
#define END 		123
#define OF 		124
#define IF 		125
#define THEN 		126
#define ELSE 		127
#define FOR 		128
#define TO 		129
#define DOWNTO 		130
#define DO 		131
#define NEW 		132
#define DISPOSE		133 
#define VIRGULA 	134
#define PONTO_E_VIRGULA 135
#define DOIS_PONTOS 	136
#define PONTO 		137
#define OPERADOR_DE_ATRIBUICAO 	138
#define OPERADOR_DE_SUBFAIXA 	139
#define SOMA 		140
#define SUBTRACAO 	141
#define ASTERISCO 	142
#define DIVISAO 	143
#define ENDERECO 	144
#define VALOR_DE_PONTEIRO 	145
#define MOD 		146
#define AND 		147
#define OR 		148
#define NOT 		149
#define IGUALDADE 	150
#define DESIGUALDADE 	151
#define MENOR 		152
#define MENOR_OU_IGUAL 	153
#define MAIOR 		154
#define MAIOR_OU_IGUAL 	155
#define ABRE_PARENTESIS 156
#define FECHA_PARENTESIS	 157
#define ABRE_COLCHETE 	158
#define FECHA_COLCHETE 	159
#define CONDICIONAL_TERNARIO 	160
#define VALOR 		161
#define IDENTIFICADOR 	162
#define ESPACO		163
#define FIM_DE_ARQUIVO	164

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char messages[1000] = ""; 

unsigned int lc = 0;
unsigned int ln;
unsigned int ncol = 0;

int retorno(int  valor_token, int tamanho){
	ncol+= tamanho;
	return valor_token;
}

void mensagemErro(char *message, unsigned int ln) {
char buffer[50];
sprintf(buffer, "Erro na linha %i %s.\n", ln, message);
strcat(messages, buffer);
}
 
void mostrarMensagens() {
if(strlen(messages) > 0){
		printf("\n%s", messages);
	}

	printf("%d lines\n%d colunas\n", lc,ncol);
} 

%}

caractere		\'.\'
flutuante		[+-]?[0-9]+\.[0-9]+([eE][+-]?[0-9]{1,2})?
inteiro			[+-]?[0-9]+
identificador		[a-zA-Z][a-zA-Z0-9_]*
espaco			[ \t]+
erro			.

%x comentario string


%%

[pP]rogram|PROGRAM		{return retorno(PROGRAM,yyleng);}
[pP]rocedure|PROCEDURE		{return retorno(PROCEDURE,yyleng);}
[fF]unction|FUNCTION		{return retorno(FUNCTION,yyleng);}
[cC]onst|CONST			{return retorno(CONST,yyleng);}
[tT]ype|TYPE			{return retorno(TYPE,yyleng);}
[vV]ar|VAR			{return retorno(VAR,yyleng);}
[aA]rray|ARRAY			{return retorno(ARRAY,yyleng);}
[bB]oolean|BOOLEAN		{return retorno(BOOLEAN,yyleng);}
[cC]har|CHAR			{return retorno(CHAR,yyleng);}
[iI]nteger|INTEGER		{return retorno(INTEGER,yyleng);}
[rR]eal|REAL			{return retorno(REAL,yyleng);}
[rR]ecord|RECORD		{return retorno(RECORD,yyleng);}
[bB]egin|BEGIN			{return retorno(BEGIN_,yyleng);}
[eE]nd|END			{return retorno(END,yyleng);}
[oO]f|OF			{return retorno(OF,yyleng);}
[iI]f|IF			{return retorno(IF,yyleng);}
[tT]hen|THEN			{return retorno(THEN,yyleng);}
[eE]lse|ELSE			{return retorno(ELSE,yyleng);}
[fF]or|FOR			{return retorno(FOR,yyleng);}
[tT]o|TO			{return retorno(TO,yyleng);}
[dD]own[tT]o|DOWNTO		{return retorno(DOWNTO,yyleng);}
[dD]o|DO			{return retorno(DO,yyleng);}
[nN]ew|NEW			{return retorno(NEW,yyleng);}
[dD]ispose|DISPOSE		{return retorno(DISPOSE,yyleng);}
\,				{return retorno(VIRGULA,yyleng);}
\;				{return retorno(PONTO_E_VIRGULA,yyleng);}
\:				{return retorno(DOIS_PONTOS,yyleng);}
\.				{ncol+=yyleng); return PONTO;}
":="				{return retorno(OPERADOR_DE_ATRIBUICAO,yyleng);}
				{return retorno(OPERADOR_DE_SUBFAIXA,yyleng);}
\+				{return retorno(SOMA,yyleng);}
\-				{return retorno(SUBTRACAO,yyleng);}
\*				{return retorno(ASTERISCO,yyleng);}
\/				{return retorno(DIVISAO,yyleng);}
\@				{return retorno(ENDERECO,yyleng);}
\^				{return retorno(VALOR_DE_PONTEIRO,yyleng);}
[mM]od|MOD			{return retorno(MOD,yyleng);}
[aA]nd|AND			{return retorno(AND,yyleng);}
[oO]r|OR			{return retorno(OR,yyleng);}
[nN]ot|NOT			{return retorno(NOT,yyleng);}
\=				{return retorno(IGUALDADE,yyleng);}
"<>"				{return retorno(DESIGUALDADE,yyleng);}
\< 				{return retorno(MENOR,yyleng);}
"<="				{return retorno(MENOR_OU_IGUAL,yyleng);}
\>				{return retorno(MAIOR,yyleng);}
">="				{return retorno(MAIOR_OU_IGUAL,yyleng);}
\(				{return retorno(ABRE_PARENTESIS,yyleng);}
\)				{return retorno(FECHA_PARENTESIS,yyleng);}
\[				{return retorno(ABRE_COLCHETE,yyleng);}
\]				{return retorno(FECHA_COLCHETE,yyleng);}
\?				{return retorno(CONDICIONAL_TERNARIO,yyleng);}
\n				{++lc;ncol=0;}
\0				{return retorno(FIM_DE_ARQUIVO,yyleng);}	
[tT]rue|TRUE			{return retorno(VALOR,yyleng);}
[fF]alse|FALSE			{return retorno(VALOR,yyleng);}


\{					{BEGIN(comentario); ln = lc;}
<comentario>[^\{\}\n<EOF>]*		;
<comentario>\n				++lc;
<comentario><<EOF>>			{mensagemErro("Comentário não terminado", ln); yyterminate( );}
<comentario>\}				BEGIN(INITIAL);


\"					{BEGIN string; ln = lc;}
<string>[^\"\n<<EOF>>]*			;
<string>\n				++lc;
<string><<EOF>>				{mensagemErro("String não terminada", ln); yyterminate( );}
<string>\"				{BEGIN INITIAL; printf("VALOR");}

{caractere}				return VALOR;
{flutuante}				return VALOR;
{inteiro}				return VALOR;
{identificador}				return IDENTIFICADOR;
{espaco}				return ESPACO;
{erro}					mensagemErro("Identificador inválido", lc);

%%
int main(int argc, char** argv) {
	yyin = fopen(argv[1], "r");
	
	while (yylex());	
	mostrarMensagens( );
	return EXIT_SUCCESS;
}
int yywrap() {
	return 1;
}

